package top.rainbowecho.gateway.security.config;

import cn.hutool.core.util.ArrayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.social.security.SpringSocialConfigurer;
import top.rainbowecho.gateway.security.authentication.mail.MailAuthenticationConfig;
import top.rainbowecho.gateway.security.authentication.open.OpenIdAuthenticationConfig;
import top.rainbowecho.gateway.security.captcha.CaptchaOnceFilter;

/**
 * @author rainbow
 * @since 2019/12/25 17:46
 */
@Configuration
@EnableResourceServer
@RefreshScope
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    private AuthenticationSuccessHandler authenticationSuccessHandler;

    private AuthenticationFailureHandler authenticationFailureHandler;

    private CaptchaOnceFilter captchaOnceFilter;

    private MailAuthenticationConfig mailAuthenticationConfig;

    private SpringSocialConfigurer socialConfigurer;

    private OpenIdAuthenticationConfig openIdAuthenticationConfig;

    @Autowired
    public void setOpenIdAuthenticationConfig(OpenIdAuthenticationConfig openIdAuthenticationConfig) {
        this.openIdAuthenticationConfig = openIdAuthenticationConfig;
    }

    @Autowired
    public void setSocialConfigurer(SpringSocialConfigurer socialConfigurer) {
        this.socialConfigurer = socialConfigurer;
    }

    @Autowired
    public void setMailAuthenticationConfig(MailAuthenticationConfig mailAuthenticationConfig) {
        this.mailAuthenticationConfig = mailAuthenticationConfig;
    }

    @Autowired
    public void setCaptchaOnceFilter(CaptchaOnceFilter captchaOnceFilter) {
        this.captchaOnceFilter = captchaOnceFilter;
    }

    @Autowired
    public void setAuthenticationSuccessHandler(AuthenticationSuccessHandler authenticationSuccessHandler) {
        this.authenticationSuccessHandler = authenticationSuccessHandler;
    }

    @Autowired
    public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
        this.authenticationFailureHandler = authenticationFailureHandler;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
//        放行的uri
        String[] authenticationUrls = new String[] {GatewayApiConstants.MAIL_LOGIN_AND_REGISTER_PAGE,
                GatewayApiConstants.FORM_LOGIN_PAGE,
                GatewayApiConstants.MAIL_REGISTER,
                GatewayApiConstants.FORM_REGISTER};
        String[] swaggerUiUrls = new String[] {
                "/swagger-ui.html",
                "/webjars/**",
                "/swagger-resources/**",
                "/v2/**"};

        String[] permitUris = ArrayUtil.append(authenticationUrls, swaggerUiUrls);

        http.addFilterBefore(this.captchaOnceFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                .loginPage(GatewayApiConstants.FORM_LOGIN_PAGE)
                .successHandler(this.authenticationSuccessHandler)
                .failureHandler(this.authenticationFailureHandler)
            .and()
                .authorizeRequests()
                .antMatchers(permitUris)
                .permitAll()
                .anyRequest()
                .authenticated()
            .and()
                .apply(this.mailAuthenticationConfig)
            .and()
                .apply(this.socialConfigurer)
            .and()
                .apply(this.openIdAuthenticationConfig)
            .and()
                .csrf()
                .disable();
    }
}
